package daos

import (
	"gorm.io/gorm"
	"gorm.io/gorm/clause"
	"sanrenx.com/xyxf/app/models"
	"sanrenx.com/xyxf/pkg/orm"
	"strconv"
)

/**
 * @Description:文章
 */
type ArticleDao struct {
	DB *gorm.DB
}

/**
 * @Description: 获取分类下文章（排除被专辑收录）数量
 * @receiver dao
 * @param categoryIds 分类ID数组
 * @param exclude 是否排除
 * @return count 数量
 * @return err 异常信息
 */
func (dao *ArticleDao) GetArticleCountByCategory(cpIds []int, exclude bool) (count int64, err error) {
	tx := dao.DB.Table("article").
		Select([]string{
			"id",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range cpIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}

	// 非全部
	if isNotAll {
		//获取子分类
		categoryDao := CategoryDao{orm.DB}
		categoryIds, cErr := categoryDao.GetCategoryIdsByPid(cpIds)
		if cErr != nil {
			return 0, cErr
		}

		idsCount := len(categoryIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("category_id NOT IN ?", categoryIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("category_id = ?", categoryIds[0])
				} else {
					tx = tx.Where("category_id IN ?", categoryIds)
				}
			}
		} else {
			return 0, nil
		}
	}

	if err = tx.Where("included = ?", false). //未被收录
							Where("deleted_at is NUll"). //未删除
							Count(&count).
							Error; err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}

	return count, nil
}

/**
 * @Description: 获取分类下文章（排除被专辑收录）
 * @receiver dao
 * @param offset 起始
 * @param size 数量
 * @param categoryIds 分类ID数组
 * @param exclude 排除
 * @param orderBy 排序
 * @return ids 文章ID数组
 * @return list 文章column数组
 * @return err 异常信息
 */
func (dao *ArticleDao) GetPageArticleColumnByCategory(offset int, size int, cpIds []int, exclude bool, orderBy string) (ids []string, list []*orm.Column, err error) {
	tx := dao.DB.Table("article").
		Select([]string{
			"id",
			"hot",
			"created_at",
		})

	isNotAll := true //是否分类0：查询全部分类
	for _, cId := range cpIds {
		if cId == 0 {
			isNotAll = false
			break
		}
	}
	// 非全部
	if isNotAll {
		//获取子分类
		categoryDao := CategoryDao{orm.DB}
		categoryIds, cErr := categoryDao.GetCategoryIdsByPid(cpIds)
		if cErr != nil {
			return nil, nil, cErr
		}

		idsCount := len(categoryIds) //分类数量
		if idsCount > 0 {
			if exclude { //排除
				tx = tx.Where("category_id NOT IN ?", categoryIds)
			} else {
				if idsCount == 1 {
					tx = tx.Where("category_id = ?", categoryIds[0])
				} else {
					tx = tx.Where("category_id IN ?", categoryIds)
				}
			}
		} else {
			return nil, nil, nil
		}
	}

	order := orm.OrderByNewDesc
	if orderBy == "hot" {
		order = orm.OrderByHotDesc
	}

	if err = tx.Where("included", false). //未被收录
						Where("deleted_at is NUll"). //未删除
						Order(order).
						Offset(offset).
						Limit(size).
						Find(&list).
						Error; err != nil && err != gorm.ErrRecordNotFound {
		return nil, nil, err
	}

	//提出IDs
	for _, item := range list {
		ids = append(ids, strconv.FormatUint(item.ID, 10))
	}

	return ids, list, nil
}

/**
 * @Description: 专辑收录文章数量
 * @receiver dao
 * @param id 专辑ID
 * @return count 文章数量
 * @return err 异常信息
 */
func (dao *ArticleDao) GetArticleCountByAlbum(id uint64) (count int64, err error) {

	//获取专辑文章IDs
	if err = dao.DB.Table("article_album").
		Select("article_id").
		Where("deleted_at is NULL").
		Where("album_id = ?", id).
		Count(&count).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return 0, err
	}

	return count, nil
}

/**
 * @Description: 获取专辑详情及关联文章
 * @receiver dao
 * @param id 专辑ID
 * @return ids 专辑文章ID数组
 * @return err 异常信息
 */
func (dao *ArticleDao) GetPageArticleIDsByAlbum(offset int, size int, id uint64) (ids []string, err error) {

	//获取专辑文章IDs
	if err = dao.DB.Table("article_album").
		Select("article_id").
		Where("deleted_at is NULL").
		Where("album_id = ?", id).
		Offset(offset).
		Limit(size).
		Find(&ids).
		Error; err != nil && err != gorm.ErrRecordNotFound {
		return nil, err
	}

	return ids, nil
}

/**
 * @Description: 文章详情
 * @receiver dao
 * @param id 文章ID
 * @return data 文章
 * @return err 异常信息
 */
func (dao *ArticleDao) GetArticle(id uint64) (*models.ArticleDetails, error) {
	//文章模型
	var data models.ArticleDetails
	// 查询数据
	if err := dao.DB.Unscoped().
		Table("article").
		Preload(clause.Associations). //预加载全部关联
		Where("id = ?", id).
		First(&data).
		Error; err != nil {
		//无数据
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}

	return &data, nil
}
